package org.hs.phd.odi.tracking.tracker.particlefilter.observation;

import org.hs.phd.odi.tracking.tracker.Histogram;
import org.hs.phd.odi.tracking.tracker.TrackWindow;
import org.hs.phd.odi.tracking.tracker.particlefilter.core.ObservationModel;
import org.hs.phd.odi.tracking.tracker.particlefilter.core.Particle;
import org.hs.phd.odi.tracking.tracker.particlefilter.tracker.ParticleStateTrackShapeConvertor;
import org.hs.phd.odi.tracking.tracker.similaritymeasure.BhattacharyaCoefficientSimilartyMeasure;

import com.googlecode.javacv.cpp.opencv_core.IplImage;

public class HistogramMatchingObservationModel<T> implements ObservationModel<T> {

	private static final int LAMBDA = 20;
	private final Histogram targetHistogram;
	private Histogram tempHistogram;
	private BhattacharyaCoefficientSimilartyMeasure measure;
	private final TrackWindow trackWindowPrototype;
	private final ParticleStateTrackShapeConvertor<T> stateToTrackShape;

	public HistogramMatchingObservationModel(Histogram targetHistogram, TrackWindow trackWindowPrototype, ParticleStateTrackShapeConvertor<T> stateToTrackShape) {
		this.targetHistogram = targetHistogram;
		this.trackWindowPrototype = trackWindowPrototype;
		this.stateToTrackShape = stateToTrackShape;
		tempHistogram = targetHistogram.getCopy();
		measure = new BhattacharyaCoefficientSimilartyMeasure();
	}

	@Override
	public float computeLikelihood(IplImage nextFrame, Particle<T> particle) {
		TrackWindow trackWindow = trackWindowPrototype.getCopy();
		stateToTrackShape.updateTrackWindowUsingParticleState(trackWindow, particle.getCurrentState());
		
		tempHistogram.calculateFrom(nextFrame, trackWindow);
		float similarity = measure.calculateSimilarity(targetHistogram, tempHistogram);
		
		float likelihood = (float) Math.exp(-LAMBDA*(1-similarity));

		return likelihood;
	}

}
